﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.Mvc;
using Sendz.Domain;
using Sendz.Model;
using Sendz.WebUI.Helpers;
using Sendz.WebUI.Authorization;
using Sendz.WebUI.Models;

namespace Sendz.WebUI.Controllers
{
    // Ref: http://stackoverflow.com/questions/759519/c-centralizing-repeating-viewdata-in-mvc
    [UserInfo] // Reference UserHelpers.cs for attribute override method; allows global user parameter access
    public class AccountController : AjaxFriendlyController
    {
        #region Repository injection //////////////////////////////////

        // Aggregate repositories, injected by container factory in /Infrastructure
        private readonly IUserRepository dbUser;
        private readonly IIdentityRepository dbIdentity;
        private readonly IFormRepository dbForm;
        private readonly IAutoResponderRepository dbAutoResponder;
        public AccountController(IUserRepository dbUser, IIdentityRepository dbIdentity, IFormRepository dbForm, IAutoResponderRepository dbAutoResponder)
        {
            this.dbUser = dbUser;
            this.dbIdentity = dbIdentity;
            this.dbForm = dbForm;
            this.dbAutoResponder = dbAutoResponder;
        }

        #endregion

        #region Action: Login, Logout //////////////////////////////////

        [HttpGet]
        public ActionResult Login()
        {
            //TempData["Message"] = "Hello, welcome to Frontdesk Beta!";
            var viewModel = new LoginViewModel() { Username = (HttpContext.Request.Cookies["FrontdeskUsername"] != null) ? HttpContext.Request.Cookies["FrontdeskUsername"].Value : string.Empty, Password = (HttpContext.Request.Cookies["FrontdeskPassword"] != null) ? HttpContext.Request.Cookies["FrontdeskPassword"].Value : string.Empty, RememberMe = (HttpContext.Request.Cookies["FrontdeskUsername"] != null) ? true : false };
            return View(viewModel);
        }

        [Authorize(Roles = "Admin")]
        [HttpGet]
        public ActionResult LoginAs(Guid id, Guid adminKey)
        {
            var userToBecome = dbUser.GetUserByKey(id);
            if (userToBecome != null)
            {
                var confirmAdmin = dbUser.GetUserByKey(adminKey);
                if (confirmAdmin != null)
                {
                    SetAuthenticationCookie(userToBecome.Username, false);
                    var userRecord = dbUser.GetUserByName(userToBecome.Username);
                    TempData["Message"] = "You are now logged in as " + userRecord.Firstname + "!";
                    return Redirect("/");
                }
            }
            return Redirect("/Admin/ListUsers");
        }

        [HttpPost]
        public ActionResult Login(string username, string password, bool rememberme, string returnUrl)
        {
            if (string.IsNullOrEmpty(username))
            {
                ModelState.AddModelError("Username", "You must specify a username to login");
            }
            if (string.IsNullOrEmpty(password))
            {
                ModelState.AddModelError("Password", "You must specify a password to login");
            }
            if (ViewData.ModelState.IsValid)
            {
                var provider = new CustomMembershipProvider();
                var loginSuccessful = provider.ValidateUser(username, password);
                if (loginSuccessful)
                {
                    // Set cookies to recall this if rememberme requested
                    var cookieHelp = new CookieHelpers();
                    if (rememberme)
                    {
                        cookieHelp.SetCookie("FrontdeskUsername", username);
                        cookieHelp.SetCookie("FrontdeskPassword", password);
                    }
                    else
                    {
                        cookieHelp.RemoveCookie("FrontdeskUsername");
                        cookieHelp.RemoveCookie("FrontdeskPassword");
                    }
                    SetAuthenticationCookie(username, rememberme);
                    var user = Membership.GetUser(true) as CustomMembershipUser;
                    // Todo: learn more about tickets and expirations
                    var userRecord = dbUser.GetUserByName(username);
                    TempData["Message"] = "Welcome to Frontdesk, " + userRecord.Firstname + "!";
                    if (!string.IsNullOrEmpty(returnUrl))
                        return Redirect(returnUrl);
                    else
                        return Redirect("/Form/List"); // We use Redirect literals throughout because of issues redirecting during Ajax.Beginform that occur otherwise; this is a conscious choice
                }
                else
                    ModelState.AddModelError("_FORM", "The username or password provided is incorrect, please try again");
            }
            // Re-populate the viewmodel
            var viewModel = new LoginViewModel() { Username = (HttpContext.Request.Cookies["FrontdeskUsername"] != null) ? HttpContext.Request.Cookies["FrontdeskUsername"].Value : string.Empty, Password = (HttpContext.Request.Cookies["FrontdeskPassword"] != null) ? HttpContext.Request.Cookies["FrontdeskPassword"].Value : string.Empty, RememberMe = (HttpContext.Request.Cookies["FrontdeskUsername"] != null) ? true : false };
            return View(viewModel);
        }

        public virtual void SetAuthenticationCookie(string username, bool isPersistent)
        {           
            FormsAuthentication.SetAuthCookie(username, isPersistent);
        }

        public void Logout()
        {
            // Always clear potential rememberme cookies when user asks to logout
            var cookieHelp = new CookieHelpers();
            cookieHelp.RemoveCookie("FrontdeskUsername");
            cookieHelp.RemoveCookie("FrontdeskPassword");
            var user = Membership.GetUser(true) as CustomMembershipUser;
            if (user != null)
            {
                var userRecord = dbUser.GetUserByName(user.UserName);
                FormsAuthentication.SignOut();
                TempData["Message"] = "Thanks for using Frontdesk, " + userRecord.Firstname + "!";
            }
            Response.Redirect("/");
        }

        #endregion

        #region Action: LostPassword ////////////////////////

        [HttpGet]
        public ActionResult LostPassword()
        {
            var viewModel = new LostPasswordViewModel();
            return View(viewModel);
        }

        [HttpPost]
        public ActionResult LostPassword(LostPasswordViewModel viewModel)
        {
            if (ModelState.IsValid)
            {
                var tryUser = dbUser.GetUserByEmail(viewModel.Email);
                if (tryUser != null)
                {
                    if (tryUser.Username == viewModel.Username)
                    {
                        // User is valid, allow password reset
                        var userHelper = new UserHelpers();
                        var textHelper = new TextHelpers();
                        TempData["Message"] = userHelper.ResetPassword(dbUser.GetUserByKey(tryUser.UserKey), textHelper.RandomString(7));
                        return Redirect("/Account/Login");
                    }
                    ModelState.AddModelError("Username", "Sorry, but this username doesn't match the email you provided");
                }
                else
                    ModelState.AddModelError("Email", "Sorry, that email address was not found in our system, please try again");
            }
            return View(viewModel);
        }

        #endregion

        #region Action: MyAccount ////////////////////////////

        [HttpGet]
        public ActionResult MyAccount()
        {
            // Password reset only in the short term
            // Todo: expand this to include more options
            var thisUser = Membership.GetUser(true) as CustomMembershipUser;
            var viewModel = new ResetPasswordViewModel();           
            viewModel.UserKey = (Guid)thisUser.ProviderUserKey;
            return View(viewModel);
        }

        [HttpPost]
        public ActionResult MyAccount(ResetPasswordViewModel viewModel)
        {
            if (ModelState.IsValid)
            {
                var userHelper = new UserHelpers();
                TempData["Message"] = userHelper.ResetPassword(dbUser.GetUserByKey(viewModel.UserKey), viewModel.Password);
                return Redirect("/Form/List");
            }
            return View(viewModel);
        }

        #endregion

        #region Action: ValidateEmail /////////////////////////

        [HttpGet]
        public ActionResult ValidateEmail(Guid id)
        {
            if (dbUser.ValidateEmailByKey(id))
                TempData["Message"] = "Thanks for approving your email address!";
            else
                TempData["Message"] = "The link you used to validate your email address is no longer valid";
            return Redirect("/account/validationdone");
        }

        [HttpGet]
        public ActionResult ValidationDone()
        {
            return View();
        }

        #endregion
    }
}
